package com.example.mall.config.handler;

import com.example.mall.common.Constants;
import com.example.mall.common.MallException;
import com.example.mall.common.ServiceResultEnum;
import com.example.mall.config.annotation.TokenToAdminUser;
import com.example.mall.dao.AdminUserTokenMapper;
import com.example.mall.entity.AdminUserToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

@Component
public class TokenToAdminUserMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private AdminUserTokenMapper adminUserTokenMapper;

    public TokenToAdminUserMethodArgumentResolver() {
    }

    /**
     * 判断是否支持解析通过@TokenToAdminUser注解的方法参数
     * @param parameter 方法参数
     * @return 布尔值
     */
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.hasParameterAnnotation(TokenToAdminUser.class)) {
            return true;
        }
        return false;
    }

    /**
     * 通过解析方法参数中的TokenToAdminUser注解以及请求中的token，获取管理员用户的令牌信息，并进行相关的验证和异常处理。
     * @param parameter 方法参数，可以通过该参数了解方法参数的特征，判断是否需要执行解析操作。
     * @param mavContainer MAV容器，提供了对Model和View的访问权限，可以通过它向视图层传递数据或进行一些预处理操作。
     * @param webRequest 是对当前请求的封装
     * @param binderFactory 用于创建和设置WebDataBinder对象的工厂，可以用于进行数据绑定和验证等操作。
     * @return ok:token对象 no:null/exception
     */
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        if (parameter.getParameterAnnotation(TokenToAdminUser.class) instanceof TokenToAdminUser) {
            String token = webRequest.getHeader("token");
            if (null != token && !"".equals(token) && token.length() == Constants.TOKEN_LENGTH) {
                AdminUserToken adminUserToken = adminUserTokenMapper.selectByToken(token);
                if (adminUserToken == null) {
                    MallException.fail(ServiceResultEnum.ADMIN_NOT_LOGIN_ERROR.getResult());
                } else if (adminUserToken.getExpireTime().getTime() <= System.currentTimeMillis()) {
                    MallException.fail(ServiceResultEnum.ADMIN_TOKEN_EXPIRE_ERROR.getResult());
                }
                return adminUserToken;
            } else {
                MallException.fail(ServiceResultEnum.ADMIN_NOT_LOGIN_ERROR.getResult());
            }
        }
        return null;
    }

}
